package com.cpkso.buss.backend.user.service;

import java.util.Date;
import java.util.List;

import javax.transaction.Transactional;

import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.cpkso.buss.backend.exception.EntityHasExistException;
import com.cpkso.buss.backend.exception.GivenNullParamException;
import com.cpkso.buss.backend.exception.NoSuchDataException;
import com.cpkso.buss.backend.user.dao.RoleDao;
import com.cpkso.buss.backend.user.dao.UserDao;
import com.cpkso.buss.backend.user.domain.Role;
import com.cpkso.buss.backend.user.domain.User;
import com.cpkso.buss.backend.user.vo.UserVo;
import com.runze.base.web.Response;

/**
 * 权限分配service
 * 
 * 按name查找用户
 * 新增权限
 * 修改权限
 * 删除权限
 * 
 * 显示所有权限
 * 按id查找权限
 * 
 * 每次登录成功需要重设盐和密码，更新ip，登录时间
 * 
 * 
 * @author wrzhxy@qq.com
 * @date 2018年3月18日
 */
@Service
@Transactional
public class UserService {
	private final static String ROLE_USER = "user";
	private final static String ROLE_MANAGER = "manager";
	
	public Response findByNameAndValid(String name) {
		if (!StringUtils.hasText(name)) throw new GivenNullParamException();
		User user = userDao.findByNameAndVerify(name, 1);
		if (user == null) return new Response("null");
		return new Response(user);
	}
	
	// 创建账户
	public void create(User user) throws GivenNullParamException, EntityHasExistException {
		if (user == null || !StringUtils.hasText(user.getName()) || !StringUtils.hasText(user.getPassword())) throw new GivenNullParamException();
		// TODO 继续安全判断
		// 判断用户名是否存在，若存在，不让注册
		User findOneByName = userDao.findOneByName(user.getName());
		if (findOneByName != null) throw new EntityHasExistException("用户名已存在！");
		
		// 生成盐
		RandomNumberGenerator rng = new SecureRandomNumberGenerator();
		ByteSource salt = rng.nextBytes();
		// 将盐插入数据库
		user.setSalt(salt.toBase64());
		// 生成加密后的密码
		String hashedPasswordBase64 = new Sha256Hash(user.getPassword(), salt, 1024).toBase64();
		user.setPassword(hashedPasswordBase64);
		
		user.setVerify(0);
		user.setCharge(0.5);
		user.setCreateTime(new Date());
		user.setUpdateTime(null);
		userDao.save(user);
	}
	// 分配角色
	public void grant(Long userId, Long roleId) throws GivenNullParamException, NoSuchDataException {
		if (userId == null || roleId == null) throw new GivenNullParamException();
		
		User user = userDao.findById(userId).get();
		Role role = roleDao.findById(roleId).get();
		if (user == null || role == null) throw new NoSuchDataException();
		
		user.addRole(role);
		
		userDao.save(user);
	}
	
	// 移除角色
	public void revoke(Long userId, Long roleId) {
		if (userId == null || roleId == null) throw new GivenNullParamException();
		
		User user = userDao.findById(userId).get();
		Role role = roleDao.findById(roleId).get();
		if (user == null || role == null) throw new NoSuchDataException();
		
		user.removeRole(role);
		
		userDao.save(user);
	}
	
	// 修改用户信息
	public void modify(User user) throws GivenNullParamException, NoSuchDataException {
		if (user == null) throw new GivenNullParamException();
		Long id = user.getId();
		User userDb = userDao.findById(id).get();
		if (userDb == null) throw new NoSuchDataException();
		
		String name = user.getName();
		if (StringUtils.hasText(name)) userDb.setName(name);
		
//		user.getPassword()
		// TODO 修改密码
//		String password = user.getPassword();
		
		Double charge = user.getCharge();
		if (charge != null) {
			userDb.setCharge(charge);
		}
		
		userDb.setUpdateTime(new Date());
		userDao.save(userDb);
	}
	/**
	 * 重置密码
	 */
	public void resetPassword(Long userId) throws GivenNullParamException, NoSuchDataException {
		if (userId == null) throw new GivenNullParamException();
		User userDb = userDao.findById(userId).get();
		if (userDb == null) throw new NoSuchDataException();
		// 重置密码
		String password = "123456";
		// 生成盐
		RandomNumberGenerator rng = new SecureRandomNumberGenerator();
		ByteSource salt = rng.nextBytes();
		// 将盐插入数据库
		userDb.setSalt(salt.toBase64());
		// 生成加密后的密码
		String hashedPasswordBase64 = new Sha256Hash(password, salt, 1024).toBase64();
		userDb.setPassword(hashedPasswordBase64);
		userDb.setUpdateTime(new Date());
		userDao.save(userDb);
	}
	/**
	 * 用户自己修改自己的账户
	 * @param user
	 * @param userId
	 */
	public void modify(User user, Long userId) throws GivenNullParamException, NoSuchDataException {
		if (user == null || userId == null) throw new GivenNullParamException();
		Long id = user.getId();
		if (id != null && id != userId) throw new GivenNullParamException("无权修改别人的账户！！！");
		
		User userDb = userDao.findById(userId).get();
		if (userDb == null) throw new NoSuchDataException();
		
		String name = user.getName();
		if (StringUtils.hasText(name)) userDb.setName(name);
		
//		user.getPassword()
		// TODO 修改密码
		String password = user.getPassword();
		if (StringUtils.hasText(password)) {
			// 生成盐
			RandomNumberGenerator rng = new SecureRandomNumberGenerator();
			ByteSource salt = rng.nextBytes();
			// 将盐插入数据库
			userDb.setSalt(salt.toBase64());
			// 生成加密后的密码
			String hashedPasswordBase64 = new Sha256Hash(user.getPassword(), salt, 1024).toBase64();
			userDb.setPassword(hashedPasswordBase64);
		}
		
		userDb.setUpdateTime(new Date());
		userDao.save(userDb);
	}
	
	/**
	 * 审核
	 * TODO 返回结果 Response
	 */
	public Response verify(Long userId) throws GivenNullParamException, NoSuchDataException {
		if (userId == null) throw new GivenNullParamException();
		User userDb = userDao.findById(userId).get();
		if (userDb == null) throw new NoSuchDataException();
		
		userDb.setVerify(userDb.getVerify() == 0 ? 1 : 0);
		Role role = roleDao.findByName(ROLE_USER);
		userDb.addRole(role);
		userDao.save(userDb);
		return new Response(userDb.getVerify());
	}
	/**
	 * 升权 员工到主管
	 */
	public void promote(Long userId) throws GivenNullParamException, NoSuchDataException {
		if (userId == null) throw new GivenNullParamException();
		User userDb = userDao.findById(userId).get();
		if (userDb == null) throw new NoSuchDataException();
		Role role = roleDao.findByName(ROLE_MANAGER);
		userDb.addRole(role);
		userDb.setCharge(0.55);
		userDao.save(userDb);
	}
	/**
	 * 降权 主管到员工
	 * @param userId
	 */
	public void demotion(Long userId) {
		if (userId == null) throw new GivenNullParamException();
		User userDb = userDao.findById(userId).get();
		if (userDb == null) throw new NoSuchDataException();
		Role role = roleDao.findByName(ROLE_MANAGER);
		userDb.removeRole(role);
		userDb.setCharge(0.50);
		userDao.save(userDb);
	}
	/**
	 * 显示所有用户
	 */
	public Response findAll() {
		List<UserVo> all = (List<UserVo>) userDao.findAllVo();
		return new Response(all);
	}
	
	@Autowired
	private UserDao userDao;
	@Autowired
	private RoleDao roleDao;

}
